package aole.visq.draw;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;

import aole.util.ColorButton;
import aole.util.DialogCreator;
import aole.util.DoubleField;
import aole.util.IntegerField;

public class VisqFrame extends JFrame implements WindowListener {
	private static final long		serialVersionUID	= 1L;

	private DrawApp					app;
	private AnimationPanel			animPanel;

	// drawing / brush / eraser
	private JToggleButton			btnBrush;
	private JToggleButton			btnEraser;
	private JRadioButtonMenuItem	mBrush;
	private JRadioButtonMenuItem	mEraser;

	// settings dialog
	private DialogCreator			settingsDialog;
	private IntegerField			txtFPS				= new IntegerField( 5 );
	private IntegerField			txtFrames			= new IntegerField( 5 );
	private DoubleField				txtBrushSize		= new DoubleField( 5 );
	private DoubleField				txtEraserSize		= new DoubleField( 5 );
	private ColorButton				btnBGColor			= new ColorButton();
	private JCheckBox				chkSmoothing		= new JCheckBox();
	private IntegerField			txtDegree			= new IntegerField( 5 );

	private JCheckBoxMenuItem		mSkinPrevious;

	private JCheckBoxMenuItem		mSkinNext;

	private JToggleButton			btnSkinPrevious;

	private JToggleButton			btnSkinNext;

	public VisqFrame( DrawApp a ) {
		app = a;
		animPanel = new AnimationPanel( a );
		setFocusable( true );
		// addKeyListener( this );
		addWindowListener( this );
	}

	public void setAnimationWidth( int width ) {
		animPanel.setAnimationWidth( width );
		animPanel.repaint();
	}

	public void setCurrentFrame( int frame ) {
		animPanel.setCurrentFrame( frame );
	}

	private void showSettingsDialog() {
		int fps = app.getFPS();
		txtFPS.setValue( fps );

		int tf = app.getTotalFrames();
		txtFrames.setValue( tf );

		float bw = app.getBrushWidth();
		txtBrushSize.setValue( bw );

		float ew = app.getEraserWidth();
		txtEraserSize.setValue( ew );

		Color c = app.getBackgroundColor();
		btnBGColor.setColor( c );

		boolean s = app.isSmoothingOn();
		chkSmoothing.setSelected( s );

		int sd = app.getSmoothingDegree();
		txtDegree.setValue( sd );

		settingsDialog.setVisible( true );

		if( settingsDialog.getSelectedOption() == DialogCreator.OK_OPTION ) {
			int fps2 = txtFPS.getValue();
			if( fps2 != fps ) app.setFPS( fps2 );

			int tf2 = txtFrames.getValue();
			if( tf2 != tf ) app.setTotalFrames( tf2 );

			float bw2 = (float) txtBrushSize.getValue();
			if( bw2 != bw ) app.setBrushWidth( bw2 );

			float ew2 = (float) txtEraserSize.getValue();
			if( ew2 != ew ) app.setEraserWidth( ew2 );

			Color c2 = btnBGColor.getColor();
			if( !c2.equals( c ) ) app.setBackgroundColor( c2 );

			boolean s2 = chkSmoothing.isSelected();
			if( s2 != s ) app.setSmoothing( s2 );

			int sd2 = txtDegree.getValue();
			if( sd2 != sd ) app.setSmoothingDegree( sd2 );
		}
	}

	private void createToolbar() {
		JToolBar toolbar = new JToolBar();
		add( toolbar, BorderLayout.NORTH );

		// toolbar
		JButton btnNew = new JButton(
				DrawApp.getIcon( "/images/size24/new.png" ) );
		btnNew.setActionCommand( "file_new" );
		btnNew.addActionListener( app );
		toolbar.add( btnNew );

		JButton btnLoad = new JButton(
				DrawApp.getIcon( "/images/size24/open.png" ) );
		btnLoad.setActionCommand( "file_load" );
		btnLoad.addActionListener( app );
		toolbar.add( btnLoad );

		JButton btnSave = new JButton(
				DrawApp.getIcon( "/images/size24/save.png" ) );
		btnSave.setActionCommand( "file_save" );
		btnSave.addActionListener( app );
		toolbar.add( btnSave );

		JButton btnSaveAs = new JButton(
				DrawApp.getIcon( "/images/size24/save_as.png" ) );
		btnSaveAs.setActionCommand( "file_save_as" );
		btnSaveAs.addActionListener( app );
		toolbar.add( btnSaveAs );
		toolbar.addSeparator();

		JButton btnUndo = new JButton(
				DrawApp.getIcon( "/images/size24/undo.png" ) );
		btnUndo.setActionCommand( "undo" );
		btnUndo.addActionListener( app );
		toolbar.add( btnUndo );
		btnUndo.setVisible( false );

		JButton btnRedo = new JButton(
				DrawApp.getIcon( "/images/size24/redo.png" ) );
		btnRedo.setActionCommand( "redo" );
		btnRedo.addActionListener( app );
		toolbar.add( btnRedo );
		btnRedo.setVisible( false );
		// toolbar.addSeparator();

		JButton btnClear = new JButton(
				DrawApp.getIcon( "/images/size24/clear.png" ) );
		btnClear.setActionCommand( "clear" );
		btnClear.addActionListener( app );
		toolbar.add( btnClear );

		JButton btnCopy = new JButton(
				DrawApp.getIcon( "/images/size24/copy.png" ) );
		btnCopy.setActionCommand( "copy" );
		btnCopy.addActionListener( app );
		toolbar.add( btnCopy );

		JButton btnPaste = new JButton(
				DrawApp.getIcon( "/images/size24/paste.png" ) );
		btnPaste.setActionCommand( "paste" );
		btnPaste.addActionListener( app );
		toolbar.add( btnPaste );
		toolbar.addSeparator();

		btnSkinPrevious = new JToggleButton(
				DrawApp.getIcon( "/images/size24/image_previous.png" ) );
		btnSkinPrevious.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent arg0 ) {
				app.setSkinPrevious( btnSkinPrevious.isSelected() );
			}
		} );
		toolbar.add( btnSkinPrevious );

		btnSkinNext = new JToggleButton(
				DrawApp.getIcon( "/images/size24/image_next.png" ) );
		btnSkinNext.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent arg0 ) {
				app.setSkinNext( btnSkinNext.isSelected() );
			}
		} );
		toolbar.add( btnSkinNext );
		toolbar.addSeparator();

		ButtonGroup drawGroup = new ButtonGroup();

		btnBrush = new JToggleButton(
				DrawApp.getIcon( "/images/size24/brush.png" ) );
		btnBrush.setActionCommand( "brush" );
		btnBrush.addActionListener( app );
		drawGroup.add( btnBrush );
		toolbar.add( btnBrush );

		btnEraser = new JToggleButton(
				DrawApp.getIcon( "/images/size24/eraser.png" ) );
		btnEraser.setActionCommand( "eraser" );
		btnEraser.addActionListener( app );
		drawGroup.add( btnEraser );
		toolbar.add( btnEraser );

		final JButton btnStrokeColor = new JButton(
				DrawApp.getIcon( "/images/size24/color_chooser.png" ) );
		btnStrokeColor.setBackground( Color.black );
		btnStrokeColor.setFocusPainted( false );
		btnStrokeColor.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				Color c = JColorChooser.showDialog( (JButton) e.getSource(),
						"Set Stroke Color", btnStrokeColor.getBackground() );
				app.setStrokeColor( c );
				btnStrokeColor.setBackground( c );
			}
		} );
		toolbar.add( btnStrokeColor );
	}

	public void createAndShowGui() {
		// settings dialog
		settingsDialog = new DialogCreator( this, "Settings" );
		settingsDialog.addField( "Frames / Second", txtFPS );
		settingsDialog.addField( "Animation Length", txtFrames );
		settingsDialog.addField( "Brush Size", txtBrushSize );
		settingsDialog.addField( "Eraser Size", txtEraserSize );
		settingsDialog.addField( "Background Color", btnBGColor );
		settingsDialog.addField( "Line Smoothing", chkSmoothing );
		settingsDialog.addField( "Degree of Smoothing", txtDegree );
		settingsDialog.pack();

		// toolbar
		createToolbar();

		// animation panel
		add( animPanel, BorderLayout.SOUTH );

		// canvas
		JPanel drawPanel = new JPanel();
		drawPanel.add( app.getCanvas() );
		JScrollPane scroll = new JScrollPane( drawPanel );
		add( scroll, BorderLayout.CENTER );

		// menus
		createMenuBar();

		// frame
		setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
		pack();
		setVisible( true );
	}

	private void createMenuBar() {
		// set the menu bar
		JMenuBar mbar = new JMenuBar();
		setJMenuBar( mbar );

		// **** FILE MENU ****
		JMenu mfile = new JMenu( "File" );
		mbar.add( mfile );

		JMenuItem mfilenew = new JMenuItem( "New...",
				DrawApp.getIcon( "/images/size24/new.png" ) );
		mfilenew.setActionCommand( "file_new" );
		mfilenew.addActionListener( app );
		mfilenew.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_N,
				ActionEvent.CTRL_MASK ) );
		mfile.add( mfilenew );

		JMenuItem btnLoad = new JMenuItem( "Open...",
				DrawApp.getIcon( "/images/size24/open.png" ) );
		btnLoad.setActionCommand( "file_load" );
		btnLoad.addActionListener( app );
		btnLoad.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_O,
				ActionEvent.CTRL_MASK ) );
		mfile.add( btnLoad );

		JMenuItem btnSave = new JMenuItem( "Save",
				DrawApp.getIcon( "/images/size24/save.png" ) );
		btnSave.setActionCommand( "file_save" );
		btnSave.addActionListener( app );
		btnSave.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_S,
				ActionEvent.CTRL_MASK ) );
		mfile.add( btnSave );

		JMenuItem btnSaveAs = new JMenuItem( "Save As...",
				DrawApp.getIcon( "/images/size24/save_as.png" ) );
		btnSaveAs.setActionCommand( "file_save_as" );
		btnSaveAs.addActionListener( app );
		mfile.add( btnSaveAs );

		mfile.addSeparator();

		JMenuItem mExportMovie = new JMenuItem( "Export Movie..." );
		mExportMovie.setActionCommand( "export_movie" );
		mExportMovie.addActionListener( app );
		mfile.add( mExportMovie );

		JMenuItem mExportImages = new JMenuItem( "Export Images..." );
		mExportImages.setActionCommand( "export_images" );
		mExportImages.addActionListener( app );
		mfile.add( mExportImages );

		mfile.addSeparator();

		JMenuItem mFileExit = new JMenuItem( "Exit" );
		mFileExit.setActionCommand( "exit" );
		mFileExit.addActionListener( app );
		mfile.add( mFileExit );

		// **** EDIT MENU ****
		JMenu medit = new JMenu( "Edit" );
		mbar.add( medit );

		JMenuItem mUndo = new JMenuItem( "Undo",
				DrawApp.getIcon( "/images/size24/undo.png" ) );
		mUndo.setActionCommand( "undo" );
		mUndo.addActionListener( app );
		mUndo.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_Z,
				ActionEvent.CTRL_MASK ) );
		medit.add( mUndo );

		JMenuItem mRedo = new JMenuItem( "Redo",
				DrawApp.getIcon( "/images/size24/redo.png" ) );
		mRedo.setActionCommand( "redo" );
		mRedo.addActionListener( app );
		mRedo.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_Y,
				ActionEvent.CTRL_MASK ) );
		medit.add( mRedo );

		medit.addSeparator();

		JMenuItem mClear = new JMenuItem( "Clear",
				DrawApp.getIcon( "/images/size24/clear.png" ) );
		mClear.setActionCommand( "clear" );
		mClear.addActionListener( app );
		mClear.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_X, 0 ) );
		medit.add( mClear );

		JMenuItem mCopy = new JMenuItem( "Copy",
				DrawApp.getIcon( "/images/size24/copy.png" ) );
		mCopy.setActionCommand( "copy" );
		mCopy.addActionListener( app );
		mCopy.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_C,
				ActionEvent.CTRL_MASK ) );
		medit.add( mCopy );

		JMenuItem mPaste = new JMenuItem( "Paste",
				DrawApp.getIcon( "/images/size24/paste.png" ) );
		mPaste.setActionCommand( "paste" );
		mPaste.addActionListener( app );
		mPaste.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_V,
				ActionEvent.CTRL_MASK ) );
		medit.add( mPaste );

		medit.addSeparator();

		JMenuItem mSettings = new JMenuItem( "Settings..." );
		mSettings.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				showSettingsDialog();
			}
		} );
		medit.add( mSettings );

		// **** DRAW MENU ****
		JMenu mdraw = new JMenu( "Draw" );
		mbar.add( mdraw );

		ButtonGroup group = new ButtonGroup();
		mBrush = new JRadioButtonMenuItem( "Brush",
				DrawApp.getIcon( "/images/size24/brush.png" ) );
		mBrush.setActionCommand( "brush" );
		mBrush.addActionListener( app );
		mBrush.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_B, 0 ) );
		group.add( mBrush );
		mdraw.add( mBrush );

		mEraser = new JRadioButtonMenuItem( "Eraser",
				DrawApp.getIcon( "/images/size24/eraser.png" ) );
		mEraser.setActionCommand( "eraser" );
		mEraser.addActionListener( app );
		mEraser.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_E, 0 ) );
		group.add( mEraser );
		mdraw.add( mEraser );

		mdraw.addSeparator();

		JMenuItem mInc = new JMenuItem( "Increase draw size" );
		mInc.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				app.increaseDrawSize();
			}
		} );
		mInc.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_W, 0 ) );
		mdraw.add( mInc );

		JMenuItem mDec = new JMenuItem( "Decrease draw size" );
		mDec.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				app.decreaseDrawSize();
			}
		} );
		mDec.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_Q, 0 ) );
		mdraw.add( mDec );

		mdraw.addSeparator();

		JMenuItem mStrokeColor = new JMenuItem( "Brush Color",
				DrawApp.getIcon( "/images/size24/color_chooser.png" ) );
		mStrokeColor.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				Color c = JColorChooser.showDialog( (Component) e.getSource(),
						"Set Stroke Color", app.getStrokeColor() );
				app.setStrokeColor( c );
			}
		} );
		mStrokeColor
				.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_C, 0 ) );
		mdraw.add( mStrokeColor );

		// **** DRAW MENU ****
		JMenu manim = new JMenu( "Animation" );
		mbar.add( manim );

		JMenuItem mSetKey = new JMenuItem( "Set Key",
				DrawApp.getIcon( "/images/size24/key.png" ) );
		mSetKey.setActionCommand( "key_set" );
		mSetKey.addActionListener( app );
		mSetKey.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_S, 0 ) );
		manim.add( mSetKey );

		JMenuItem mRemoveKey = new JMenuItem( "Remove Key",
				DrawApp.getIcon( "/images/size24/list_remove.png" ) );
		mRemoveKey.setActionCommand( "key_remove" );
		mRemoveKey.addActionListener( app );
		mRemoveKey.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_R, 0 ) );
		manim.add( mRemoveKey );

		JMenuItem mAddKey = new JMenuItem( "Add key to next frame" );
		mAddKey.setActionCommand( "key_add_next" );
		mAddKey.addActionListener( app );
		mAddKey.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_TAB, 0 ) );
		manim.add( mAddKey );

		manim.addSeparator();

		mSkinPrevious = new JCheckBoxMenuItem( "Skin previous frame",
				DrawApp.getIcon( "/images/size24/image_previous.png" ) );
		mSkinPrevious.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent arg0 ) {
				app.setSkinPrevious( mSkinPrevious.isSelected() );
			}
		} );
		manim.add( mSkinPrevious );

		mSkinNext = new JCheckBoxMenuItem( "Skin next frame",
				DrawApp.getIcon( "/images/size24/image_next.png" ) );
		mSkinNext.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent arg0 ) {
				app.setSkinNext( mSkinNext.isSelected() );
			}
		} );
		manim.add( mSkinNext );

		// **** HELP MENU ****
		JMenu mhelp = new JMenu( "Help" );
		mbar.add( mhelp );

		JMenuItem mAbout = new JMenuItem( "About..." );
		mAbout.addActionListener( new ActionListener() {
			@Override
			public void actionPerformed( ActionEvent e ) {
				showAboutDialog();
			}
		} );
		mhelp.add( mAbout );
	}

	public void showAboutDialog() {
		String strAbout = "Vision Quest Draw (v" + app.getVersionString()
				+ ")\n\n";
		strAbout += "Created by: Bhupendra Aole\n";
		strAbout += "Website: https://code.google.com/p/visqdraw\n\n";
		strAbout += "Icons: http://www.oxygen-icons.org\n";
		strAbout += "(http://www.iconarchive.com/show/oxygen-icons-by-oxygen-icons.org.html)\n\n";
		strAbout += "External Libraries:\n";
		strAbout += " + JPen (www.jpen.sourceforge.net)\n";
		strAbout += " + JCodec (http://www.jcodec.org)";

		JOptionPane.showMessageDialog( this, strAbout );
	}

	public void setBrush() {
		btnBrush.setSelected( true );
		mBrush.setSelected( true );
	}

	public void setEraser() {
		btnEraser.setSelected( true );
		mEraser.setSelected( true );
	}

	public void setSkinPrevious( boolean v ) {
		mSkinPrevious.setSelected( v );
		btnSkinPrevious.setSelected( v );
	}

	public void setSkinNext( boolean v ) {
		mSkinNext.setSelected( v );
		btnSkinNext.setSelected( v );
	}

	@Override
	public void windowClosing( WindowEvent arg0 ) {
		app.systemExit();
	}

	@Override
	public void windowClosed( WindowEvent arg0 ) {}

	@Override
	public void windowActivated( WindowEvent arg0 ) {}

	@Override
	public void windowDeactivated( WindowEvent arg0 ) {}

	@Override
	public void windowDeiconified( WindowEvent arg0 ) {}

	@Override
	public void windowIconified( WindowEvent arg0 ) {}

	@Override
	public void windowOpened( WindowEvent arg0 ) {}
}
